# ========= 构建 .S -> .elf / .hex =========
RISCV_PREFIX ?= riscv-none-embed
CC      := $(RISCV_PREFIX)-gcc
OBJCOPY := $(RISCV_PREFIX)-objcopy
OBJDUMP := $(RISCV_PREFIX)-objdump
# Python/打包脚本（把字节版 imem.hex -> 32bit/行的 imem_words.hex）
PYTHON := python
PACK_IMEM:= tools/pack_imem.py
#编译参数
MARCH ?= rv32i
MABI  ?= ilp32
#相关文件存放路径
ENV_DIR    ?= env
MACROS_DIR ?= macros
TEST_DIR   ?= tests/rv32ui
LINK_LD    ?= $(ENV_DIR)/link.ld
ENTRY_S    ?= $(wildcard $(ENV_DIR)/crt0.S)
BUILD   := build
ELF_DIR := $(BUILD)/elf
HEX_DIR := $(BUILD)/hex
DUMP_DIR:= $(BUILD)/dump
CFLAGS   := -march=$(MARCH) -mabi=$(MABI) -nostdlib -nostartfiles -Wl,--no-relax -D__riscv_xlen=32
INCLUDES := -I$(MACROS_DIR) -I$(ENV_DIR) 
SRCS  := $(sort $(wildcard $(TEST_DIR)/*.S))
ELFS  := $(patsubst $(TEST_DIR)/%.S,$(ELF_DIR)/%.elf,$(SRCS))
DUMPS := $(patsubst $(ELF_DIR)/%.elf,$(DUMP_DIR)/%.dump,$(ELFS))
# 原来的字节版 imem.hex（objcopy 产物）
IMEMS_BYTES := $(patsubst $(ELF_DIR)/%.elf,$(HEX_DIR)/%/imem.hex,$(ELFS))
# 新增：打包后的 word 版 imem_words.hex（TB/IMEM 使用它）
IMEMS_WORDS := $(patsubst $(ELF_DIR)/%.elf,$(HEX_DIR)/%/imem_words.hex,$(ELFS))
# 提取名字列表（如 add、beq、…）
TESTS := $(notdir $(basename $(SRCS)))

.PHONY: list
list:
	@echo "TEST_DIR = $(TEST_DIR)"
	@echo "Found $(words $(SRCS)) source(s):"
	@$(foreach s,$(SRCS),echo " - $(s)";)

.PHONY: elf
elf: $(ELFS) 
	@echo "Built $(words $(ELFS)) ELF(s) into $(ELF_DIR)"

$(ELF_DIR)/%.elf: $(TEST_DIR)/%.S $(LINK_LD) | $(ELF_DIR) $(DUMP_DIR)
	@echo "[CC] $< -> $@  (link.ld=$(abspath $(LINK_LD)))"
	$(CC) $(CFLAGS) $(INCLUDES) \
	      -T $(LINK_LD) \
	      -Wl,-Map,$(DUMP_DIR)/$*.map \
	      -Wl,--cref \
	      $(ENTRY_S) $< -o $@

.PHONY: hex
hex: elf $(IMEMS_BYTES) $(IMEMS_WORDS)
	@echo "HEX generated under $(HEX_DIR)"

# 导出“完整镜像”，含 .boot/.text/.rodata 及 .data 的加载镜像（LMA）
$(HEX_DIR)/%/imem.hex: $(ELF_DIR)/%.elf
	@echo "[HEX] image $< -> $@  (full image to IMEM)"
	@mkdir -p $(@D)
	@rm -rf $@
	$(OBJCOPY) -O verilog --gap-fill 0x00 $< $@

# imem.hex(字节) -> imem_words.hex(32位指令/行)【供仿真使用】
$(HEX_DIR)/%/imem_words.hex: $(HEX_DIR)/%/imem.hex $(PACK_IMEM)
	@echo "[PACK] $< -> $@  (bytes -> words, little-endian)"
	@mkdir -p $(@D)          # 创建“目标所在目录”
	@rm -rf $@               # 防止目标目前是个目录/旧文件
	$(PYTHON) $(PACK_IMEM) $< $@


# ======= 单测便捷目标（为每个测试生成 *_elf / *_hex / *_dump）=======
.PHONY: $(addsuffix _elf,$(TESTS)) $(addsuffix _hex,$(TESTS)) $(addsuffix _dump,$(TESTS))

# foo_elf -> build/elf/foo.elf
$(addsuffix _elf,$(TESTS)): %_elf: $(ELF_DIR)/%.elf
	@true

# foo_hex -> build/hex/foo/imem.hex + imem_words.hex（隐含依赖 foo.elf）
$(addsuffix _hex,$(TESTS)): %_hex: $(HEX_DIR)/%/imem.hex $(HEX_DIR)/%/imem_words.hex
	@echo "[DONE] $* hex -> $(HEX_DIR)/$*/"

# foo_dump -> build/dump/foo.dump（隐含依赖 foo.elf）
$(addsuffix _dump,$(TESTS)): %_dump: $(DUMP_DIR)/%.dump
	@true

.PHONY: dump
dump: $(DUMPS)
	@echo "Dumped $(words $(DUMPS)) file(s) into $(DUMP_DIR)"

# ===== 规则：反汇编 =====
$(DUMP_DIR)/%.dump: $(ELF_DIR)/%.elf | $(DUMP_DIR)
	@echo "[DUMP] $< -> $@"
	$(OBJDUMP) -h -d $< > $@

# 一键生成所有 map（其实编 ELF 时就会有）
.PHONY: maps
maps: $(patsubst $(ELF_DIR)/%.elf,$(DUMP_DIR)/%.map,$(ELFS))
	@echo "Maps at $(DUMP_DIR)/"

# 快速检查 tohost/从 map
.PHONY: check_tohost
check_tohost:
	@grep -Hn -i tohost $(DUMP_DIR)/*.map || echo "No map files yet; build ELFs first."

# src/Makefile 末尾新增
.PHONY: names
names:
	@echo $(TESTS)

$(BUILD) $(ELF_DIR) $(HEX_DIR) $(DUMP_DIR):
	@mkdir -p $@
$(HEX_DIR)/%:
	@mkdir -p $(@D)

.PHONY: clean
clean:
	rm -rf $(BUILD)
